using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Comteck.Utils;
using WinformApp = System.Windows.Forms.Application;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using Comteck.Winforms.Extensions;
using System.Windows;
using System.Drawing;

namespace Comteck.Winforms.Utils {
  /// <summary>
  /// 
  /// </summary>
  public partial class WinformHelper : BaseLog {

    #region 常量

    private static readonly Version Windows8Version = new Version(6, 2);

    #endregion

    #region 在所有窗口中查询已经打开的窗体

    /// <summary>
    /// 在所有窗口中查询已经打开的窗体
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static T GetActiveForm<T>() where T : Form {
      foreach (Form form in WinformApp.OpenForms) {
        if (typeof(T) == form.GetType()) {
          return form as T;
        }
      }

      return null;
    }

    /// <summary>
    /// 在所有窗口中查询已经打开的窗体
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static Form GetActiveForm(Type type){
      foreach (Form form in WinformApp.OpenForms) {
        if (form.GetType() == type) {
          return form as Form;
        }
      }

      return null;
    }

    #endregion

    #region 将表单上的值填充到实体类中
    /// <summary>
    /// 将表单上的值填充到实体类中
    /// </summary>
    /// <typeparam name="T">实体类类型</typeparam>
    /// <param name="container">System.Windows.Forms.Control,控件所在的容器</param>
    /// <returns></returns>
    public static T FillForm2Model<T>(Control container) where T : class, new() {
      return FillForm2Model(container, default(T), String.Empty);
    }

    /// <summary>
    /// 将表单上的值填充到实体类中
    /// </summary>
    /// <typeparam name="T">实体类类型</typeparam>
    /// <param name="container">System.Windows.Forms.Control,控件所在的容器</param>
    /// <param name="prefix">表单控件中的前缀,比如ck_</param>
    /// <returns></returns>
    public static T FillForm2Model<T>(Control container, string prefix) where T : class, new() {
      return FillForm2Model(container, default(T), prefix);
    }


    /// <summary>
    /// 将表单上的值填充到实体类中
    /// </summary>
    /// <typeparam name="T">实体类类型</typeparam>
    /// <param name="container">System.Windows.Forms.Control,控件所在的容器</param>
    /// <param name="model">实体类值</param>
    /// <returns></returns>
    public static T FillForm2Model<T>(Control container, T model) where T : class, new() {
      return FillForm2Model(container, model, String.Empty);
    }

    /// <summary>
    /// 将表单上的值填充到实体类中
    /// </summary>
    /// <typeparam name="T">实体类类型</typeparam>
    /// <param name="container">System.Windows.Forms.Control,控件所在的容器</param>
    /// <param name="model">实体类值</param>
    /// <param name="prefix">表单控件中的前缀,比如ck_</param>
    /// <returns></returns>
    public static T FillForm2Model<T>(Control container, T model, string prefix)
      where T : class, new() {
      // 控件容器为空
      if (container == null) {
        throw new ArgumentNullException("container", "请确定Control container容器不为空！");
      }

      // 创建Model的实例
      if (model == null || model.Equals(default(T))) {
        model = Activator.CreateInstance<T>();
      }

      // 取得容器的所有控件
      Control.ControlCollection controls = container.Controls;

      // 容器内没有控件
      if (controls == null || controls.Count == 0) {
        return model;
      }

      // 控件前缀
      prefix = prefix ?? String.Empty;

      // 取得Model中所有的属性
      PropertyInfo[] propertys = model.GetType().GetProperties(BindingFlags.GetProperty
        | BindingFlags.Public | BindingFlags.Instance);

      // 属性名称
      string name = null;

      // 页面控件
      Control control = null;

      // 控件的值
      object value = null;

      // 转换后的值
      object convertValue = null;

      foreach (PropertyInfo pi in propertys) {
        // 取得属性名称
        name = prefix + pi.Name;

        // 根据名称找到控件
        control = controls[name];

        // 如果控件没有找到,则不做处理
        if (control == null) {
          continue;
        }

        value = GetWinControlValue(control);

        // 如果属性值为NULL,则不赋值
        if (ValidateHelper.IsNull(value) == true) {
          continue;
        }

        // 转换后的值
        convertValue = ConvertType(value, pi.PropertyType);

        if (convertValue.Is(EnumValidateType.Null)) {
          continue;
        }

        // 设置属性值
        pi.SetValue(model, convertValue, null);
      }

      return model;
    }

    /// <summary>
    /// 得到System.Windows.Forms.Control服务器控件的值
    /// </summary>
    /// <param name="control">System.Windows.Forms.Control</param>
    /// <returns></returns>
    public static object GetWinControlValue(Control control) {
      object value = null;

      if (control is TextBoxBase) {
        // 文本框,包括 TextBox,RickTextBox,MaskedTextBox
        value = ((TextBoxBase)control).Text.Trim();
      } else if (control is NumericUpDown) {
        // 数字文本框
        value = ((NumericUpDown)control).Value;
      } else if (control is DateTimePicker) {
        // 日期选择框
        value = ((DateTimePicker)control).Value;
      } else if (control is CheckBox) {
        // 复选框
        value = ((CheckBox)control).CheckState;
      } else if (control is ComboBox) {
        // 下拉框
        value = ((ComboBox)control).SelectedValue;
      } else if (control is RadioButton) {
        // 下拉框
        value = ((RadioButton)control).Checked;

        // ---------------- 以下是针对 DEV 控件的
      } else if (control is DevExpress.XtraEditors.LookUpEdit) {
        // 文本框 LookUpEdit
        value = ((DevExpress.XtraEditors.LookUpEdit)control).EditValue;
      } else if (control is DevExpress.XtraEditors.TreeListLookUpEdit) {
        // 文本框 TreeListLookUpEdit
        value = ((DevExpress.XtraEditors.TreeListLookUpEdit)control).EditValue;
      } else if (control is DevExpress.XtraEditors.ComboBoxEdit) {
        // 文本框 ComboBoxEdit
        value = ((DevExpress.XtraEditors.ComboBoxEdit)control).EditValue;
      } else if (control is DevExpress.XtraEditors.DateEdit) {
        // 文本框 DateEdit
        value = ((DevExpress.XtraEditors.DateEdit)control).EditValue;
      } else if (control is DevExpress.XtraEditors.TimeEdit) {
        // 文本框 TimeEdit
        value = ((DevExpress.XtraEditors.TimeEdit)control).EditValue;
      } else if (control is DevExpress.XtraEditors.RadioGroup) {
        // 文本框 RadioGroup
        value = ((DevExpress.XtraEditors.RadioGroup)control).EditValue;
      } else if (control is DevExpress.XtraEditors.ColorEdit) {
        // 文本框 MemoExEdit
        //((DevExpress.XtraEditors.ColorEdit) control). = value.To<string>(String.Empty);
      } else if (control is DevExpress.XtraEditors.TextEdit) {
        // 文本框,包括 TextEdit,MemoEdit
        value = ((DevExpress.XtraEditors.BaseEdit)control).EditValue;
      } else if (control is DevExpress.XtraEditors.MemoExEdit) {
        // 文本框 MemoExEdit
        value = ((DevExpress.XtraEditors.MemoExEdit)control).EditValue;
      } else if (control is DevExpress.XtraEditors.CheckEdit) {
        // 文本框 CheckEdit
        value = (int)((DevExpress.XtraEditors.CheckEdit)control).CheckState;
      }

      return value;
    }

    /// <summary>
    /// 获取控件名对应的不包含前缀的字段名 add by wiejie.sun 2013/10/29
    /// </summary>
    /// <param name="controlName">控件名称</param>
    /// <param name="prefix">前缀</param>
    /// <returns></returns>
    public static string GetFieldNameWithoutPrefix(string controlName, string prefix) {
      //// 无前缀 
      //if (prefix.Is(EnumValidateType.Null)) {
      //  return controlName;
      //}

      // 索引
      var index = controlName.IndexOf(prefix);

      // 不包含前缀
      if (index != 0) {
        return controlName;
      }

      return controlName.Substring(prefix.Length);
    }

    /// <summary>
    /// 根据对象类型获取EF的过滤类型
    /// </summary>
    /// <param name="fieldType">字段类型</param>
    /// <returns></returns>
    public static string GetDataFilterType(Type fieldType) {
      var type = "";

      // 根据类型做不同处理
      if (fieldType == typeof(Int16) || fieldType == typeof(Nullable<Int16>)) {
        type = "short";
      } else if (fieldType == typeof(Int32) || fieldType == typeof(Nullable<Int32>)) {
        type = "int";
      } else if (fieldType == typeof(Int64) || fieldType == typeof(Nullable<Int64>)) {
        type = "long";
      } else if (fieldType == typeof(decimal) || fieldType == typeof(Nullable<decimal>)) {
        type = "decimal";
      } else if (fieldType == typeof(bool) || fieldType == typeof(Nullable<bool>)) {
        type = "bool";
      } else if (fieldType == typeof(string)) {
        type = "string";
      } else if (fieldType == typeof(DateTime) || fieldType == typeof(Nullable<DateTime>)) {
        type = "date";
      }

      return type;
    }

    #endregion

    #region 把实体类的值填充到表单中去(仅限于服务器控件)

    /// <summary>
    /// 把实体类的值填充到表单中去(仅限于服务器控件)
    /// </summary>
    /// <typeparam name="T">实体类</typeparam>
    /// <param name="container">System.Web.UI.Control,控件所在的容器</param>
    /// <param name="t">实例化</param>
    /// <param name="prefix">表单中的前缀,比如 kj_UserID</param>
    public static void FillModel2Form<T>(Control container, T t, string prefix = "") {
      // 判断为空
      if (t == null) {
        return;
      }

      // 控件容器为空
      if (container == null) {
        throw new ArgumentNullException("container", "请确定Control container容器不为空！");
      }

      // 取得容器的所有控件
      var controls = container.Controls;

      // 容器内没有控件
      if (controls == null || controls.Count == 0) {
        return;
      }

      // 控件前缀
      prefix = prefix ?? String.Empty;

      // 取得Model中所有的属性
      PropertyInfo[] propertys = t.GetType().GetProperties(BindingFlags.GetProperty
        | BindingFlags.Public | BindingFlags.Instance);

      // 页面控件
      Control control = null;

      // 属性名称
      string name = null;

      // 属性值
      object value = null;

      foreach (PropertyInfo pi in propertys) {
        // 得到属性名称
        name = prefix + pi.Name;

        // 根据名称找到控件
        control = controls[name];

        // 控件不存在
        if (control == null) {
          continue;
        }

        // 取得属性值
        value = pi.GetValue(t, null);

        // 如果属性值为空,则不做任何处理
        //if (value.Is(EnumValidateType.Null)) {
        //  continue;
        //}

        // 对控件进行赋值
        SetWinControlValue(control, value);
      }
    }

    /// <summary>
    /// 把实体类的值填充到表单中去(仅限于服务器控件)
    /// </summary>
    /// <param name="container">System.Web.UI.Control,控件所在的容器</param>
    public static void ClearWinforms(Control container) {
      // 控件容器为空
      if (container == null) {
        throw new ArgumentNullException("container", "请确定Control container容器不为空！");
      }

      // 取得容器的所有控件
      Control.ControlCollection controls = container.Controls;

      // 容器内没有控件
      if (controls == null || controls.Count == 0) {
        return;
      }

      // 遍历所有控件
      foreach (Control control in controls) {
        SetWinControlValue(control, null);
      }
    }

    /// <summary>
    /// 得到System.Windows.Forms.Control服务器控件的值
    /// </summary>
    /// <param name="control">System.Windows.Forms.Control</param>
    /// <param name="value">值</param>
    public static void SetWinControlValue(Control control, object value) {
      if (control is TextBoxBase) {
        // 文本框,包括 TextBox,RickTextBox,MaskedTextBox
        ((TextBoxBase)control).Text = value.ToString(true);
      } else if (control is NumericUpDown) {
        // 数字文本框
        ((NumericUpDown)control).Value = value.To<decimal>();
      } else if (control is DateTimePicker) {
        // 日期选择框
        ((DateTimePicker)control).Value = value.To<DateTime>();
      } else if (control is CheckBox) {
        // 复选框
        ((CheckBox)control).Checked = ConvertHelper.ToBoolean(value); ;
      } else if (control is ComboBox) {
        // 下拉框
        ((ComboBox)control).SelectedValue = value;
      } else if (control is RadioButton) {
        // 下拉框
        ((RadioButton)control).Checked = ConvertHelper.ToBoolean(value); ;

        // ---------------- 以下是针对 DEV 控件的
      } else if (control is DevExpress.XtraEditors.LookUpEdit) {
        // 文本框 LookUpEdit
        ((DevExpress.XtraEditors.LookUpEdit)control).SetEditValue2(value);
      } else if (control is DevExpress.XtraEditors.TreeListLookUpEdit) {
        // 文本框 TreeListLookUpEdit
        ((DevExpress.XtraEditors.TreeListLookUpEdit)control).EditValue = value;
      } else if (control is DevExpress.XtraEditors.ComboBoxEdit) {
        // 文本框 ComboBoxEdit
        ((DevExpress.XtraEditors.ComboBoxEdit)control).EditValue = value;
      } else if (control is DevExpress.XtraEditors.CheckedComboBoxEdit) {
        // 文本框 CheckEdit
        ((DevExpress.XtraEditors.CheckedComboBoxEdit)control).SetEditValue(value);
      } else if (control is DevExpress.XtraEditors.DateEdit) {
        // 文本框 DateEdit
        ((DevExpress.XtraEditors.DateEdit)control).EditValue = value.To<DateTime?>();
      } else if (control is DevExpress.XtraEditors.TimeEdit) {
        // 文本框 TimeEdit
        ((DevExpress.XtraEditors.TimeEdit)control).EditValue = value.To<DateTime?>();
      } else if (control is DevExpress.XtraEditors.RadioGroup) {
        // 文本框 MemoExEdit
        ((DevExpress.XtraEditors.RadioGroup)control).EditValue = value;
      } else if (control is DevExpress.XtraEditors.ColorEdit) {
        // 文本框 MemoExEdit
        //((DevExpress.XtraEditors.ColorEdit) control). = value.To<string>(String.Empty);
      } else if (control is DevExpress.XtraEditors.TextEdit) {
        // 文本框,包括 TextEdit,MemoEdit
        ((DevExpress.XtraEditors.BaseEdit)control).EditValue = value;
      } else if (control is DevExpress.XtraEditors.MemoExEdit) {
        // 文本框 MemoExEdit
        ((DevExpress.XtraEditors.MemoExEdit)control).EditValue = value;
      } else if (control is DevExpress.XtraEditors.CheckEdit) {
        // 文本框 CheckEdit
        ((DevExpress.XtraEditors.CheckEdit)control).Checked = ConvertHelper.ToBoolean(value);
      }

    }
    #endregion

    #region 设置时间的走动

    /// <summary>
    /// 设置时间的走动
    /// </summary>
    /// <param name="control"></param>
    public static void SetControlTimeMove(System.Windows.Forms.Control control) {
      // 秒表滴答滴答滴答
      bool tickTick = true;

      // 定时器
      System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
      timer.Interval = 500; // 每隔半秒钟,执行一次
      timer.Tick += (sender, e) => {
        if (tickTick) {
          control.Text = DateTime.Now.ToString("HH:mm");
        } else {
          control.Text = DateTime.Now.ToString("HH mm");
        }
        tickTick = !tickTick;
      };

      // 定时器开启
      timer.Start();
    }

    /// <summary>
    /// 设置时间的走动
    /// </summary>
    /// <param name="control"></param>
    public static void SetFullControlTimeMove(System.Windows.Forms.Control control, string format = DateTimeFormat.LONGDATETIME) {
      // 秒表滴答滴答滴答
      bool tickTick = true;

      // 定时器
      System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer {
        Interval = 500 // 每隔半秒钟,执行一次
      };
      timer.Tick += (sender, e) => {
        if (tickTick) {
          control.Text = DateTime.Now.ToString(format);
        } else {
          control.Text = DateTime.Now.ToString(format);
        }
        tickTick = !tickTick;
      };

      // 定时器开启
      timer.Start();
    }

    #endregion

    #region 创建表单

    /// <summary>
    /// 
    /// </summary>
    /// <param name="typeName"></param>
    /// <param name="assemblyName"></param>
    /// <returns></returns>
    public static Form CreateForm(string typeName, string assemblyName = null) {
      var type = AssemblyHelper.CreateType(typeName, assemblyName);

      if (type == null) {
        return null;
      }

      return AssemblyHelper.CreateInstance(type) as Form;
    }

    #endregion

    #region 对空类型进行判断转换

    /// <summary>
    /// 对空类型进行判断转换,否则转换时会发生错误
    /// </summary>
    /// <param name="value">要转换的值</param>
    /// <param name="type">转换的类型</param>
    /// <returns>转换后的值</returns>
    public static object ConvertType(object value, Type type) {
      // 如果值为空
      if (value == null) {
        return null;
      }

      // 如果是数组，则不作处理,hack by weijie.sun 2013/11/11
      if (!(value is string) && value is IEnumerable) {
        return null;
      }

      if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
        if (value == null) {
          return null;
        }

        var convert = new System.ComponentModel.NullableConverter(type);
        type = convert.UnderlyingType;
      }

      // 针对布尔类型,特殊处理
      if (type == typeof(bool)) {
        return ConvertHelper.ToBoolean(value);
      }

      return Convert.ChangeType(value, type);
    }

    #endregion

    #region 导入文件

    #endregion

    #region 导出文件

    /// <summary>
    /// 
    /// </summary>
    /// <param name="text"></param>
    /// <param name="fileName"></param>
    public static void SaveAsClientSnFile(object text, string fileName = null) {
      SaveAsFile(text, "授权文件(*.ctk)|*.ctk", fileName);
    }

    /// <summary>
    /// 导出文件
    /// </summary>
    /// <param name="text"></param>
    /// <param name="filter"></param>
    /// <param name="fileName"></param>
    public static void SaveAsFile(object text, string filter, string fileName = null) {
      var dialog = new SaveFileDialog();
      dialog.Title = "请选择文件存放路径";
      dialog.FileName = fileName;
      dialog.Filter = filter;

      if (dialog.ShowDialog() != DialogResult.OK) {
        return;
      }

      // 没有选择文件
      if (string.IsNullOrWhiteSpace(dialog.FileName)) {
        DevHelper.ShowMsg("请输入导出文件的名称");
        return;
      }

      // 鼠标样式
      Cursor.Current = Cursors.WaitCursor;

      // 文件名小写
      fileName = dialog.FileName.ToLower();

      try {
        //using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite)) {
        //  var data = Encoding.UTF8.GetBytes(text?.ToString());
        //  fileStream.Write(data, 0, data.Length);
        //  fileStream.Flush();
        //  fileStream.Close();
        //}

        using (var sw = new StreamWriter(fileName, false, new UTF8Encoding(false))) {
          sw.Write(text?.ToString());
          sw.Flush();
        }

        DevHelper.ShowMsg("文件保存成功");
      } catch (Exception ex) {
        DevHelper.ShowMsg($"文件保存失败，{ex.Message}");
      }

      Cursor.Current = Cursors.Default;
    }

    #endregion

    #region 导出已存在的文件到指定目录

    /// <summary>
    /// 导出文件
    /// </summary>
    /// <param name="text"></param>
    /// <param name="filter"></param>
    /// <param name="fileName"></param>
    public static void SaveFile(string filePath, string filter, bool openFile = false) {
      if (File.Exists(filePath) == false) {
        DevHelper.ShowMsg($"模板文件 {filePath} 不存在！");
        return;
      }

      var newPath = string.Empty;

      using (var saveFileDialog1 = new SaveFileDialog()) {
        saveFileDialog1.Title = "另存为";
        saveFileDialog1.FileName = Path.GetFileName(filePath);
        saveFileDialog1.Filter = filter;
        saveFileDialog1.AddExtension = false;

        if (saveFileDialog1.ShowDialog() != DialogResult.OK) {
          return;
        }

        File.Copy(filePath, saveFileDialog1.FileName, true);
        newPath = saveFileDialog1.FileName;
      }

      if (openFile) {

        var dialog = DevHelper.ShowMsg("文件保存成功！{0}您现在是否要打开该文件？".FormatWith(Environment.NewLine),
          "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information);

        if (dialog == DialogResult.No) {
          return;
        }

        try {
          var process = new System.Diagnostics.Process();
          process.StartInfo.FileName = newPath;
          process.StartInfo.Verb = "Open";
          process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
          process.Start();
        } catch {
          DevHelper.ShowMsg("打开失败，请检查是否已安装相应的软件！");
        }
      } else {
        DevHelper.ShowMsg("文件保存成功");
      }

    }

    #endregion

    #region 是否支持websockets

    /// <summary>
    /// 是否支持websockets
    /// </summary>
    /// <returns></returns>
    public static bool IsWebSocketsSupported() {
      var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
      if (!isWindows) {
        // Assume other OSes have websockets
        return true;
      } else {
        // Windows 8 and above has websockets
        return Environment.OSVersion.Version >= Windows8Version;
      }
    }

    #endregion

    #region 检查应用程序是否启动

    /// <summary>
    /// 判断同一目录的应用程序是否存在
    /// </summary>
    /// <returns></returns>
    public static bool IsProcessExistsBySameDirectory(out Process existsProcess, Process process = null) {
      existsProcess = null;

      // get current process
      process = process ?? Process.GetCurrentProcess();

      if (process == null) {
        return false;
      }

      // 忽略访问的进程列表
      // 因为这两个进程的某些属性一旦访问就抛出没有权限的异常
      var ignoreProcessNameList = new List<string> { "System", "Idle" };

      // add by geping@2019-05-22，调试模式下屏蔽偶发的错误：“仅完成部分的 ReadProcessMemory 或 WriteProcessMemory 请求”
      try {
        // 获取当前所有的实例
        var processList = Process.GetProcessesByName(process.ProcessName);

        // 如果存在同一目录的资料,filename = 完整路径
        // typeof(Program).Assembly.GetName().Name
        existsProcess = processList.FirstOrDefault(x =>
           !ignoreProcessNameList.Contains(x.ProcessName)
          && x.Id != process.Id
          && x.MainModule.FileName.Equals(process.MainModule.FileName, StringComparison.OrdinalIgnoreCase));

        //if (existsProcess != null) {
        //  ShowWindowAsync(existsProcess.MainWindowHandle, 5);
        //}

        return existsProcess != null;
      } catch {
        return false;
      }
    }



    #endregion

    #region 重启应用程序

    /// <summary>
    /// 重启应用程序
    /// </summary>
    public static void Restart() {
      //
      SetFormsConfirmedClosed();

      // restart
      SysGlobal.Close();
      Process.Start(WinformApp.ExecutablePath);
    }

    /// <summary>
    /// 针对目前所有打开的界面，取消关闭确认信息, FormClosing Event
    /// </summary>
    public static void SetMdiFormClosing() {
      foreach (var form in WinformApp.OpenForms) {
        if (form is FrmSkinBase frmSkinBase) {
          frmSkinBase.FormClosing += (sender, e) => {
            e.Cancel = false;
          };
        }
      }
    }

    /// <summary>
    /// 针对目前所有打开的界面，取消关闭确认信息, FormClosing Event
    /// </summary>
    public static void SetFormsConfirmedClosed() {
      foreach (var form in WinformApp.OpenForms) {
        if (form is FrmSkinBase frmSkinBase) {
          frmSkinBase.ShowConfirmWhenClose = false;
        }
      }
    }

    /// <summary>
    /// 针对目前所有打开的界面，取消关闭确认信息, FormClosing Event
    /// </summary>
    public static void SetAjaxLoadingClosed() {
      foreach (var form in WinformApp.OpenForms) {
        if (form is FrmSkinBase frmSkinBase) {
          frmSkinBase.AjaxLoadHelper?.Hide();
        }
      }
    }

    #endregion

    #region 内存回收

    /// <summary>
    /// 
    /// </summary>
    /// <param name="process"></param>
    /// <param name="minSize"></param>
    /// <param name="maxSize"></param>
    /// <returns></returns>
    [DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]
    public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);

    /// <summary>
    /// 释放内存
    /// </summary>
    public static void ClearMemory() {
      GC.Collect();
      GC.WaitForPendingFinalizers();
      if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
        SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
      }

#if DEBUG
      Logger.Info("内存清理成功");
#endif
    }

    #endregion

    #region 打开URL

    /// <summary>
    /// 
    /// </summary>
    /// <param name="url"></param>
    public static void OpenUrl(string url) {
      if (url.IsNotNullOrEmpty()) {
        var pattern = @"[a-zA-z]+://[^\s]*";
        if (Regex.IsMatch(url, pattern)) {
          Process.Start(url);
        }
      }
    }

    #endregion

    #region 对象转换成类型

    /// <summary>
    /// 对象转Decimal（支持DBNull.Value）
    /// </summary>
    /// <param name="obj"></param>
    /// <returns>如果是空转成0</returns>
    public static decimal Obj2Decimal(object obj) {
      if (obj == null || obj == DBNull.Value) {
        return 0;
      } else {
        return Convert.ToDecimal(obj);
      }
    }

    /// <summary>
    /// 对象转Int（支持DBNull.Value）
    /// </summary>
    /// <param name="obj"></param>
    /// <returns>如果是空转成0</returns>
    public static int Obj2Int32(object obj) {
      if (obj == null || obj == DBNull.Value) {
        return 0;
      } else {
        return Convert.ToInt32(obj);
      }
    }

    /// <summary>
    /// 对象转String（支持DBNull.Value）
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static string Obj2String(object obj) {
      if (obj == null || obj == DBNull.Value) {
        return null;
      } else {
        return Convert.ToString(obj);
      }
    }

    #endregion

    #region 获得分割后的日期集合

    /// <summary>
    /// 获得分割后的日期段集合
    /// </summary>
    /// <param name="beginDate">开始日期</param>
    /// <param name="dateTime">结束日期</param>
    /// <param name="size">每页数量</param>
    /// <example>如传入2023.1.1,2023.1.31,30，返回4个日期段</example>
    /// <returns>日期段</returns>
    public static List<(DateTime beginDate, DateTime endDate)> GetSplitDateRangleList(DateTime beginDate, DateTime endDate, int size) {
      var result = new List<(DateTime beginDate, DateTime endDate)>();

      // 结束日期比开始的小，直接跳出
      if (endDate < beginDate) {
        return result;
      }

      var dateList = new List<DateTime>();
      for(var date = beginDate; date<= endDate; date = date.AddDays(1)) {
        dateList.Add(date);
      }

      var splitDateList = dateList.SplitPageList(size);
      foreach(var splitDateEntity in splitDateList) {
        result.Add((splitDateEntity.Min(), splitDateEntity.Max()));
      }

      return result;
    }

    #endregion

    #region 获取当前DPI
    
    /// <summary>
    /// 获取DPI缩放比例
    /// </summary>
    /// <returns></returns>
    public static SizeF GetDpiSizeF() {
      try {
        var dpiXProperty = typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | BindingFlags.Static);
        var dpiYProperty = typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | BindingFlags.Static);
        var dpiX = (int) dpiXProperty.GetValue(null, null);
        var dpiY = (int) dpiYProperty.GetValue(null, null);
        var dpixRatio = (float) dpiX / 96;
        var dpiyRatio = (float) dpiY / 96;
        return new SizeF(dpixRatio, dpiyRatio);
      } catch (Exception ex) {
        Logger.Error("获取DPI失败", ex);
        return new SizeF(1f, 1f);
      }
    }

    #endregion


  }
}
